//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
#ifndef __BOOT_STORE_H
#define __BOOT_STORE_H

#include <bootDevice.h>

#ifdef __cplusplus
extern "C" {
#endif

//------------------------------------------------------------------------------
// Aliases

#define BOOT_STORE_ACCESS_READ      BOOT_DEVICE_ACCESS_READ
#define BOOT_STORE_ACCESS_WRITE     BOOT_DEVICE_ACCESS_WRITE
#define BOOT_STORE_INIT             BOOT_DEVICE_INIT

//------------------------------------------------------------------------------
//
//  Enumeration:  BOOT_STORE_OPEN_MODE
//
enum BOOT_STORE_OPEN_MODE {
    BOOT_STORE_OPEN_MODE_BINARY_REGION = 0x00010001,
    BOOT_STORE_OPEN_MODE_RESERVED_REGION = 0x00010002,
    BOOT_STORE_OPEN_MODE_PARTITION = 0x00010003
};

//------------------------------------------------------------------------------

typedef struct BOOT_STORE_OPEN_BINARY_REGION {
    UINT32 index;
} BOOT_STORE_OPEN_BINARY_REGION;

//------------------------------------------------------------------------------

typedef struct BOOT_STORE_OPEN_RESERVED_REGION {
    CHAR name[8];
} BOOT_STORE_OPEN_RESERVED_REGION;

//------------------------------------------------------------------------------

typedef struct BOOT_STORE_OPEN_PARTITION {
    UINT32 type;
    UINT32 index;
} BOOT_STORE_OPEN_PARTITION;

//------------------------------------------------------------------------------

typedef struct BOOT_STORE_BINARY_REGION_INFO {
    UINT32 size;
} BOOT_STORE_BINARY_REGION_INFO;

//------------------------------------------------------------------------------

typedef struct BOOT_STORE_RESERVED_REGION_INFO {
    CHAR name[8];
    UINT32 size;
} BOOT_STORE_RESERVED_REGION_INFO;

//------------------------------------------------------------------------------

typedef struct BOOT_STORE_PARTITION_INFO {
    UINT32 type;
    UINT32 index;
    UINT64 size;
} BOOT_STORE_PARTITION_INFO;

//------------------------------------------------------------------------------

enum BOOT_STORE_IOCTL {
    BOOT_STORE_IOCTL_GETSIZE        = 0x00010001,
    BOOT_STORE_IOCTL_SEEK           = 0x00010002,
    BOOT_STORE_IOCTL_GETPOS         = 0x00010003,
    BOOT_STORE_IOCTL_FORMAT         = 0x00010004,
    BOOT_STORE_IOCTL_LOCK_MODE      = 0x00010005
};

typedef struct BOOT_STORE_GETSIZE_PARAMS {
    UINT64 size;
} BOOT_STORE_GETSIZE_PARAMS;

typedef struct BOOT_STORE_SEEK_PARAMS {
    UINT64 position;
} BOOT_STORE_SEEK_PARAMS;

typedef struct BOOT_STORE_GETPOS_PARAMS {
    UINT64 position;
} BOOT_STORE_GETPOS_PARAMS;

enum BOOT_STORE_FORMAT_FLAGS {
    BOOT_STORE_FORMAT_SKIP_BINARY_REGIONS = (1 << 0)
};

typedef struct BOOT_STORE_FORMAT_INFO {
    UINT32 flags;
    UINT32 binaryRegions;
    BOOT_STORE_BINARY_REGION_INFO *pBinaryRegionInfo;
    UINT32 reservedRegions;
    BOOT_STORE_RESERVED_REGION_INFO *pReservedRegionInfo;
    UINT32 partitions;
    BOOT_STORE_PARTITION_INFO *pPartitionInfo;
} BOOT_STORE_FORMAT_INFO;


enum BOOT_STORE_LOCK_MODE {
    BOOT_STORE_LOCK_MODE_ULDR           = 0x00000001,
    BOOT_STORE_LOCK_MODE_OS             = 0x00000002,
    BOOT_STORE_LOCK_MODE_HWMON          = 0x00000003
};

typedef struct BOOT_STORE_LOCK_MODE_INFO {
    UINT32 mode;
} BOOT_STORE_LOCK_MODE_INFO;

//------------------------------------------------------------------------------
//
//  Function: BootStoreInit
//
//  This is proxy for BOOT_DEVICE_PFN_INIT function.
//
__inline
HANDLE
BootStoreInit(
    BOOT_DEVICE_INIT* pInit
    )
{
    BOOT_DEVICE_IFC* pIfc = NULL;
    
    if (!pInit->pfnInit(pInit->pContext, pInit->contextSize, &pIfc))
        {
        pIfc = NULL;
        }
    return pIfc;
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreDeinit
//
__inline
BOOL
BootStoreDeinit(
    HANDLE hStore
    )
{
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    return pIfc->pfnDeinit(pIfc->hDevice);
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreIoCtl
//
__inline
BOOL
BootStoreIoCtl(
    HANDLE hStore,
    DWORD code,
    VOID* pBuffer,
    DWORD size
    )
{
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    return pIfc->pfnIoCtl(pIfc->hDevice, code, pBuffer, size);
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreOpen
//
__inline
BOOL
BootStoreOpen(
    HANDLE hStore,
    DWORD access,
    DWORD mode,
    VOID *pContext,
    DWORD contextSize
    )
{
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    return pIfc->pfnOpen(pIfc->hDevice, access, mode, pContext, contextSize);
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreClose
//
__inline
BOOL
BootStoreClose(
    HANDLE hStore
    )
{
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    return pIfc->pfnClose(pIfc->hDevice);
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreRead
//
__inline
UINT32
BootStoreRead(
    HANDLE hStore,
    VOID* pBuffer,
    UINT32 size
    )
{
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    return pIfc->pfnRead(pIfc->hDevice, pBuffer, size);
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreWrite
//
__inline
UINT32
BootStoreWrite(
    HANDLE hStore,
    VOID* pBuffer,
    UINT32 size
    )
{
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    return pIfc->pfnWrite(pIfc->hDevice, pBuffer, size);
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreOpenBinaryRegion
//
//  This function opens binary region on store.
//
__inline
BOOL
BootStoreOpenBinaryRegion(
    HANDLE hStore,
    DWORD access,
    DWORD index
    )
{
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    BOOT_STORE_OPEN_BINARY_REGION info;
    info.index = index;
    return pIfc->pfnOpen(
        pIfc->hDevice, access, BOOT_STORE_OPEN_MODE_BINARY_REGION, 
        &info, sizeof(info)
        );
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreOpenReservedRegion
//
//  This function opens reserved region on store.
//
__inline
BOOL
BootStoreOpenReservedRegion(
    HANDLE hStore,
    DWORD  access,
    LPCSTR name
    )
{
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    BOOT_STORE_OPEN_RESERVED_REGION info;
    memcpy(info.name, name, sizeof(info.name));
    info.name[7] = '\0';
    return pIfc->pfnOpen(
        pIfc->hDevice, access, BOOT_STORE_OPEN_MODE_RESERVED_REGION, 
        &info, sizeof(info)
        );
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreOpenPartition
//
//  This function opens reserved region on store.
//
__inline
BOOL
BootStoreOpenPartition(
    HANDLE hStore,
    DWORD access,
    UINT32 type,
    UINT32 index
    )
{
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    BOOT_STORE_OPEN_PARTITION info;
    info.type = type;
    info.index = index;
    return pIfc->pfnOpen(
        pIfc->hDevice, access, BOOT_STORE_OPEN_MODE_PARTITION, 
        &info, sizeof(info)
        );
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreGetSize
//
__inline
UINT64
BootStoreGetSize(
    HANDLE hStore
    )
{
    BOOL rc;
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    BOOT_STORE_GETSIZE_PARAMS params;

    rc = pIfc->pfnIoCtl(
            pIfc->hDevice, BOOT_STORE_IOCTL_GETSIZE, &params, sizeof(params)
            );
    return rc ? params.size : (-1);
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreSeek
//
__inline
BOOL
BootStoreSeek(
    HANDLE hStore,
    UINT64 position
    )
{
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    BOOT_STORE_SEEK_PARAMS params;
    params.position = position;
    return pIfc->pfnIoCtl(
        pIfc->hDevice, BOOT_STORE_IOCTL_SEEK, &params, sizeof(params)
        );
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreGetPos
//
__inline
BOOL
BootStoreGetPos(
    HANDLE hStore,
    UINT64 *pPosition
    )
{
    BOOL rc;
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    BOOT_STORE_GETPOS_PARAMS params;

    rc = pIfc->pfnIoCtl(
            pIfc->hDevice, BOOT_STORE_IOCTL_GETPOS, &params, sizeof(params)
            );
    if (rc) *pPosition = params.position;
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreFormat
//
//  This function formats store.
//
__inline
BOOL
BootStoreFormat(
    HANDLE hStore,
    BOOT_STORE_FORMAT_INFO *pInfo
    )
{
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    return pIfc->pfnIoCtl(
        pIfc->hDevice, BOOT_STORE_IOCTL_FORMAT, pInfo, sizeof(*pInfo)
        );
}

//------------------------------------------------------------------------------
//
//  Function:  BootStoreLockMode
//
//  This function sets store to specified lock mode.
//
__inline
BOOL
BootStoreLockMode(
    HANDLE hStore,
    UINT32 mode
    )
{
    BOOT_DEVICE_IFC *pIfc = (BOOT_DEVICE_IFC*)hStore;
    BOOT_STORE_LOCK_MODE_INFO info;
    info.mode = mode;
    return pIfc->pfnIoCtl(
        pIfc->hDevice, BOOT_STORE_IOCTL_LOCK_MODE, &info, sizeof(info)
        );
}

//------------------------------------------------------------------------------

#ifdef __cplusplus
}
#endif

#endif // __BOOT_STORE_H
